/*
 * Daniel R Padilla
 *
 * Copyright (c) 2008, Daniel R Padilla
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.databasefacade.translator;


import java.util.ArrayList;

import org.databasefacade.select.From;
import org.databasefacade.select.Join;
import org.databasefacade.select.QueryHints;
import org.databasefacade.select.Where;
import org.databasefacade.table.Table;
import org.databasefacade.table.column.Column;
import org.databasefacade.table.column.datatype.DataType;
import org.databasefacade.update.Update;


public class DefaultAnsiSqlTranslator implements Translator
{
	private String keyJavaType = "java.math.BigDecimal";
	private String keyDataTypeSQL = "Integer";
	private short keyDataLength=10;
	private String strDelimiter="'";
	
	/*
	 * Create table methods
	 */
	public String createTableSQL(Table table, Column primaryKey)
	{
		return null;
	}
	
	/*
	 * Select translation methods
	 */
	public String getSelectColumn(String column, String tableAlias, String columnAlias) {
		String selectFieldSQL = tableAlias + "." + column + " " + columnAlias;
		if ( column.equals(columnAlias) ) {
			selectFieldSQL = tableAlias + "." + column;
		}
		return selectFieldSQL;
	}
	
	/*
	 * Update 
	 */
	public String getUpdateSQL(Update update, From from, Where where) {
		return DefaultAnsiUpdate.getUpdateAnsiSQL(update, from, where);
	}
	
	/*
	 * Hints
	 */
	public String getSelectHintSQL(QueryHints hints) {
		return ""; // AnsiSQL92 does not support hints
	}
	public QueryHints getQueryHints() {
		return new DefaultAnsiQueryHints();
	}
	
	/*
	 * Data Type translation methods
	 */
	
	/**
	 * AnsiSQL-92 DataTypes:
	 * 
	 * CHARACTER, CHARACTER VARYING, BIT, BIT VARYING, NUMERIC, DECIMAL,
	 * INTEGER, SMALLINT, FLOAT, REAL, DOUBLE PRECISION, DATE, TIME,
	 * TIMESTAMP, and INTERVAL (we are not supporting interval).
	 * 
	 * TIMESTAMP in the SQL92 spec is defined as the MS SQL Datetime 
	 * and the MYSQL Datetime and not the timestamp sql server and mysql 
	 * gave the field. 
	 *
	 */
	public String getDataTypeSQL(DataType type)
	{
	    if ( type.getColumnType() == DataType.BIGINT_TYPE ) {
	    	return "DECIMAL(19,0)";
	    } else if (type.getColumnType() == DataType.BIT_TYPE ) {
	    	return "BIT";
	    } else if (type.getColumnType() == DataType.BOOLEAN_TYPE ) {
	    	return "CHARACTER(1)";
	    } else if (type.getColumnType() == DataType.DATE_TYPE) {
	    	return "DATE";
	    } else if (type.getColumnType() == DataType.DECIMAL_TYPE ) {
	    	return "DECIMAL(" + type.getPrecision() + ", " + type.getScale() + ")";
	    } else if (type.getColumnType() == DataType.DOUBLE_TYPE ) {
	    	return "DOUBLE(" + type.getPrecision() + ", " + type.getScale() + ")";
	    } else if (type.getColumnType() == DataType.FLOAT_TYPE) {
	    	return "FLOAT";
	    } else if (type.getColumnType() == DataType.FOREIGN_KEY_TYPE ) {
	    	return getKeyDataTypeSQL();
	    } else if (type.getColumnType() == DataType.INTEGER_TYPE ) {
	    	return "INTEGER";
	    } else if (type.getColumnType() == DataType.MONEY_TYPE ) {
	    	return "DECIMAL(19,2)";
	    } else if (type.getColumnType() == DataType.AUTO_INCREMENT_TYPE ) {
	    	return getKeyDataTypeSQL();
	    } else if (type.getColumnType() == DataType.REAL_TYPE) {
	    	return "REAL";
	    } else if (type.getColumnType() == DataType.SMALLINT_TYPE ) {
	    	return "SMALLINT";
	    } else if (type.getColumnType() == DataType.STRING_TYPE ) {
	    	return "CHARACTER(" + type.getLength() + ")";
	    } else if (type.getColumnType() == DataType.TIME_TYPE) {
	    	return "TIME";
	    } else if (type.getColumnType() == DataType.TIMESTAMP_TYPE ) {
	    	return "DATETIME";
	    } else {
	    	return null; 
	    }
	}
	
	/*
	 * Assign function sql
	 */
	public String getFunctionSQL(String functionType, ArrayList parameters) {
		return DefaultAnsiFunctions.getFunctionSQL(functionType, parameters);
	}

	
	/*
	 * Join Methods
	 */
	public short getJoinNotationMode() {
		return Join.ANSI_NOTATION;
	}
	public String getAnsiJoinExtendedSQL(short joinType, String table, String alias, QueryHints hints) {
		String actualAlias = new String(alias);
		String sql = null;
		if ( table.equalsIgnoreCase(actualAlias) ) {
			actualAlias = "";
		}
		if ( joinType == Join.INNER ) {
			sql = "INNER JOIN " + table + " " + actualAlias;
		} else if ( joinType == Join.LEFT_OUTER) {
			sql =  "LEFT OUTER JOIN "  + table + " " + actualAlias;
		} else if ( joinType == Join.RIGHT_OUTER) {
			sql =  "RIGHT OUTER JOIN "  + table + " " + actualAlias;
		} else if ( joinType == Join.FULL_OUTER) {
			sql =  "FULL OUTER JOIN "  + table + " " + actualAlias;
		} else if ( joinType == Join.CROSS ) {
			sql = "CROSS JOIN "  + table + " " + actualAlias;
		} else {
			return null;
		}
		return sql;
	}
	public String buildNativeFromSQL(From from, Where where) {
		return from.getSQL();
	}
	public String buildNativeWhereSQL(From from, Where where) {
		return where.getSQL();
	}
	
	/*
	 * Key type information
	 */
	public void setKeyDataTypeSQL(String sqlType)
	{
		keyDataTypeSQL = sqlType;
	}

	public String getKeyDataTypeSQL()
	{
		return keyDataTypeSQL;		
	}

	public void setKeyJavaType(String javaType)
	{
		keyJavaType = javaType;
	}

	public String getKeyJavaType()
	{
		return keyJavaType;
	}

	public void setKeyLength(short len)
	{
		keyDataLength = len;
	}

	public short getKeyLength()
	{
		return keyDataLength;		
	}
	
	public void setStringDelimiter(String s)
	{
		this.strDelimiter = s;
	}
	
	public String getStringDelimiter()
	{
		return strDelimiter;
	}
}
